
/* File: RenderObject.js */
/**
 * RenderObject JavaScript Library
 */

/* File: RenderObject.js */	
if (!window.RO) { window.RO = {}; };
RO.Math = {};
RO.Util = {};
RO.ShaderChunk = {};
RO.RadiusScale = 1.5*2;
RO.LineType = 0;//0窄线 1，宽宽线 2,虚线

RO.ShaderChunk.pointLightShader = {
	
	vertexShader: [
	
		"uniform float amplitude;",
		"uniform float size;",
		"attribute vec3 customColor;",
		"varying vec3 vColor;",

		"void main() {",

			"vColor = vec3(1.0,1.0,1.0);",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"gl_PointSize = size;",
			"gl_Position = projectionMatrix * mvPosition;",

		"}",

	].join( "\n" ),

	fragmentShader: [

		"uniform vec3 color;",
	    "uniform sampler2D texture;",
	    "varying vec3 vColor;",

		"void main() {",

			"gl_FragColor = vec4( color * vColor, 1.0 );",
			"gl_FragColor = gl_FragColor * texture2D( texture, vec2(gl_PointCoord.x,1.0 - gl_PointCoord.y) );",
		"}",

	].join( "\n" )

};

RO.ShaderChunk.stationLightShader = {
	
	vertexShader: [

		"varying vec3 vColor;",

		"void main() {",

			"vColor = vec3(1.0,1.0,1.0);",
			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
			"gl_PointSize = 70.0;",
			"gl_Position = projectionMatrix * mvPosition;",

		"}",

	].join( "\n" ),

	fragmentShader: [

		"uniform vec3 color;",
	    "uniform sampler2D texture;",
	    "varying vec3 vColor;",

		"void main() {",

			"gl_FragColor = vec4( vColor * vColor, 1.0 );",
			"gl_FragColor = gl_FragColor * texture2D( texture, sampleUV.st );",
		"}",

	].join( "\n" )

};


RO.ShaderChunk.StreamlineShader = {
		
	vertexShader: [
		"attribute float vtTime;",
        "varying float vertexTime;",
		 
		"void main() {",
			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position.xyz, 1.0);",
			"vertexTime = vtTime;",
		"}",

	].join( "\n" ),

	fragmentShader: [

		"varying float vertexTime;",
		"uniform sampler2D texture;",
		"uniform float currentTime;",
		"uniform float sumTime;",
		"uniform vec3 color;",
		
		"float delteLength = 10.0;",
		
		"float CalculateAlpha(float cTime)",
		"{ ",
		   "float alpha = 0.0;",
		   "if(cTime > vertexTime + delteLength)",
		   "{",
			" alpha = 0.0;",
		   "}",
		   "else if(cTime < vertexTime)",
		   "{",
			 "alpha = 0.0;",
		   "}",
		   "else{",
			  
			 "alpha = (delteLength - abs(vertexTime - cTime ))/delteLength;",
			 "alpha =  alpha*alpha;",
		   "}",
		   
		   "return alpha;",
		"}",
		
		
		"void main() {",
		
			"const int num = 60;",
			"float alpha = 0.0;",
			"float delteTime = sumTime / float(num);",
			"float currenTime = mod(currentTime,delteLength);",
			"for(int i = 0;i<num;i++)",
			"{",
			  "float value = float(i)*delteTime;",
			  "alpha += CalculateAlpha(value+currenTime);",
			"}",
			
			"gl_FragColor = vec4(color.xyz,alpha);",
		"}",

	].join( "\n" )

};

RO.BaseObject = function ( ) {
	
	THREE.Object3D.call( this );
	var scope = this;
	
	this.setVisibility = function(visible) {
		this.traverse(function(obj) {
			obj.visible = visible;
		});
	};
	
	this.setShadowInteraction = function(enable) {
		this.traverse(function(obj) {
			obj.castShadow = enable;
			obj.receiveShadow = enable;
		});
	};
	
};

RO.BaseObject.prototype = Object.create( THREE.Object3D.prototype );

RO.Math.GetLength = function(start,end)
{
	var point = (new THREE.Vector3()).subVectors(start,end);
	var length = Math.sqrt(Math.pow(point.x,2)+Math.pow(point.y,2)+Math.pow(point.z,2));
	return length;
}
RO.Math.constrain = function(v, min, max){
	if( v < min )
		v = min;
	else
	if( v > max )
		v = max;
	return v;
}

RO.Math.iszero = function(value) {
	return ((value<1e-13) && (value>-1e-13));
}

//球面点和球面外的点，判断中间是否有交点,通过夹角判断
RO.Math.isIntersectionSphere = function(start,end){
	var direction = (new THREE.Vector3()).subVectors(end,start);
	var direction2 = start;
	var value = direction.x*direction2.x+direction.y*direction2.y+direction.z*direction2.z;
	if(value <= 0.0)
	{
		return true;
	}
	else{
		return false;
	}
}

//球面点和球面外的点，判断中间是否有交点，通过距离判断
RO.Math.LineIntersectionSphere = function(start,end,radius){
	var direction = (new THREE.Vector3()).subVectors(end,start);
	direction.normalize();
	var direction2 = start;
	var crossDirection = start.cross(direction);
	var value = Math.sqrt(crossDirection.x*crossDirection.x+crossDirection.y*crossDirection.y+crossDirection.z*crossDirection.z);
	
	if(value <= radius)
	{
		return true;
	}
	else{
		return false;
	}
}

RO.Math.sphericalToCartesian = function(dLongitude, dLatitude, dRadius) {
	var dRadCosLat = dRadius * Math.cos(dLatitude);
	return new THREE.Vector3(dRadCosLat*Math.sin(dLongitude), dRadius*Math.sin(dLatitude), dRadCosLat*Math.cos(dLongitude));
}

RO.Math.cartesianToSpherical = function(x, y, z) {
	var rho = Math.sqrt(x * x + y * y + z * z);
	if (RO.Math.iszero(rho))
	{
		return new THREE.Vector3(0, 0, 0);
	}
	var longitude = Math.atan2(x, z);
	var latitude = Math.asin(y / rho);
	return new THREE.Vector3(longitude, latitude, rho);
}

RO.Util.getRandomColor = function(){
	return new THREE.Color('#'+Math.floor(Math.random()*16777215).toString(16));
}

RO.Util.gifTextureAnimator = function(texture, tilesHoriz, tilesVert, numTiles, tileDispDuration) {	
	// note: texture passed by reference, will be updated by the update function.
		
	this.tilesHorizontal = tilesHoriz;
	this.tilesVertical = tilesVert;
	// how many images does this spritesheet contain?
	//  usually equals tilesHoriz * tilesVert, but not necessarily,
	//  if there at blank tiles at the bottom of the spritesheet. 
	this.numberOfTiles = numTiles;
	texture.wrapS = texture.wrapT = THREE.RepeatWrapping; 
	texture.repeat.set( 1 / this.tilesHorizontal, 1 / this.tilesVertical );

	// how long should each image be displayed?
	this.tileDisplayDuration = tileDispDuration;

	// how long has the current image been displayed?
	this.currentDisplayTime = 0;

	// which image is currently being displayed?
	this.currentTile = 0;
		
	this.update = function( milliSec )
	{
		this.currentDisplayTime += milliSec;
		while (this.currentDisplayTime > this.tileDisplayDuration)
		{
			this.currentDisplayTime -= this.tileDisplayDuration;
			this.currentTile++;
			if (this.currentTile == this.numberOfTiles)
				this.currentTile = 0;
			var currentColumn = this.currentTile % this.tilesHorizontal;
			texture.offset.x = currentColumn / this.tilesHorizontal;
			var currentRow = Math.floor( this.currentTile / this.tilesHorizontal );
			texture.offset.y = currentRow / this.tilesVertical;
		}
	};
}

RO.Util.repeatTextureAnimator = function(texture, tileDispDuration) {	
	// note: texture passed by reference, will be updated by the update function.

	texture.wrapS = THREE.RepeatWrapping;
	texture.wrapT = THREE.RepeatWrapping;
    texture.needsUpdate = true;
    texture.repeat.set( 1.0, 0.5);
	//texture.repeat.set(1.0,num);
	
	// how long should each image be displayed?
	this.tileDisplayDuration = tileDispDuration;

	// how long has the current image been displayed?
	this.currentDisplayTime = 0;

	var num = 0.002;
	
	this.update = function( milliSec )
	{
		 texture.offset.y -= num;

		this.currentDisplayTime += milliSec;
		while (this.currentDisplayTime > this.tileDisplayDuration)
		{
			this.currentDisplayTime -= this.tileDisplayDuration;
			//texture.offset.y -= num;
			
			/* if(texture.offset.y < 0.0)
			{
				texture.offset.y = 1.0;
			} */
		} 
	};
}
	
//创建航行路径，根据半径，开始，终止点，模拟被塞尔曲线
RO.Util.CreatFlyline = function(radius,start,end) {

    var point = (new THREE.Vector3()).subVectors(start,end);
	var length = Math.sqrt(Math.pow(point.x,2)+Math.pow(point.y,2)+Math.pow(point.z,2));
	
	var distanceBetweenCountryCenter = length;		
	
	//	midpoint for the curve
	var mid = new THREE.Vector3(start.x+end.x,start.y+end.y,start.z+end.z);	
	mid.x = mid.x*0.5;
	mid.y = mid.y*0.5;
	mid.z = mid.z*0.5;
	
	var midDirection = mid.clone();
	
	mid.normalize();
	mid.multiplyScalar( radius + distanceBetweenCountryCenter * 0.01 );			
  
	//	the normal from start to end
	var normal = (new THREE.Vector3()).subVectors(start,end);
	normal.normalize();

	/*				     
				The curve looks like this:
				
				midStartAnchor---- mid ----- midEndAnchor
			  /											  \
			 /											   \
			/												\
	start/anchor 										 end/anchor

		splineCurveA							splineCurveB
	*/

	var distanceHalf = distanceBetweenCountryCenter * 0.5;

	var startAnchor = start;
	var offsetA = normal.clone().multiplyScalar( distanceHalf );
	var midStartAnchor = new THREE.Vector3(mid.x + offsetA.x,mid.y + offsetA.y,mid.z + offsetA.z);				
	var midEndAnchor = new THREE.Vector3(mid.x - offsetA.x,mid.y - offsetA.y,mid.z - offsetA.z);	
	var endAnchor = end;

	//	now make a bezier curve out of the above like so in the diagram
	var splineCurveA = new THREE.CubicBezierCurve3( start, startAnchor, midStartAnchor, mid);											
	// splineCurveA.updateArcLengths();

	var splineCurveB = new THREE.CubicBezierCurve3( mid, midEndAnchor, endAnchor, end);
	// splineCurveB.updateArcLengths();

	//	how many vertices do we want on this guy? this is for *each* side
	var vertexCountDesired = Math.floor( /*splineCurveA.getLength()*/ distanceBetweenCountryCenter * 0.02 + 6 ) * 2;	

	//	collect the vertices
	var points = splineCurveA.getPoints( vertexCountDesired );

	//	remove the very last point since it will be duplicated on the next half of the curve
	points = points.splice(0,points.length-1);

	points = points.concat( splineCurveB.getPoints( vertexCountDesired ) );

	var attributes = {
        vtTime: { type: 'f', value: [] }
    };
	
	var uniforms = {
		currentTime: { type: "f", value: 0.0 },
		sumTime:     { type: "f", value: 0.0 },
		color: { type: "c", value: RO.Util.getRandomColor() },
	};
	
	var shaderMaterial = new THREE.ShaderMaterial( {
		uniforms: 		uniforms,
		attributes:     attributes,
		vertexShader:   RO.ShaderChunk.StreamlineShader.vertexShader,
		fragmentShader: RO.ShaderChunk.StreamlineShader.fragmentShader,
		blending: 		THREE.AdditiveBlending,
		depthTest: 		true,
		depthWrite: 	false,
		transparent:	true,
		sizeAttenuation: true,
	});
	
  
	var lineGeometry = new THREE.Geometry();
    lineGeometry.verticesNeedUpdate = false;
	
	var pointSize = points.length;
	
	for(var i = 0; i< pointSize;i++)
	{
		attributes.vtTime.value.push(i*10.0);
	}
	uniforms.sumTime.value = pointSize*10.0;
	
		//线构造
	lineGeometry.vertices = points;
	var line = new THREE.Line(lineGeometry,shaderMaterial);

	line.update = function(){	
	
		if(line.geometry)
		{
			uniforms.currentTime.value += 0.1;
		}	
	}	
			
	return line;
}

//创建航行路径，根据半径，开始，终止点，模拟被塞尔曲线
RO.Util.CreatSimpleline = function(start,end) {

    var points = [];
	points.push( start );
	points.push( end );
	
	var attributes = {
        vtTime: { type: 'f', value: [] }
    };
	
	var uniforms = {
		currentTime: { type: "f", value: 0.0 },
		sumTime:     { type: "f", value: 0.0 },
		color: { type: "c", value: RO.Util.getRandomColor() },
	};
	
	var shaderMaterial = new THREE.ShaderMaterial( {
		uniforms: 		uniforms,
		attributes:     attributes,
		vertexShader:   RO.ShaderChunk.StreamlineShader.vertexShader,
		fragmentShader: RO.ShaderChunk.StreamlineShader.fragmentShader,
		blending: 		THREE.AdditiveBlending,
		depthTest: 		true,
		depthWrite: 	false,
		transparent:	true,
	});
			
	var lineGeometry = new THREE.Geometry();

	var pointSize = points.length;
	
    attributes.vtTime.value.push(0.0);
	attributes.vtTime.value.push(370.0);
	
	uniforms.sumTime.value = 370.0;
	uniforms.color.value = RO.Util.getRandomColor();
	
	//线构造
	lineGeometry.vertices = points;
	var line = new THREE.Line(lineGeometry,shaderMaterial);
    line.vertexUpdate = true;
	
	line.update = function(){	
	
		if(line.geometry)
		{
		  uniforms.currentTime.value += 0.5;
		}	
	}

    line.setEnd = function(pos){
		
		 if(this.geometry.vertices.length > 0){
		  this.geometry.vertices[1] = pos;
		  this.geometry.verticesNeedUpdate = true;
		} 
	}
		
	line.setStart = function(pos){
		 if(this.geometry.vertices.length > 0){
		  this.geometry.vertices[0] = pos;
		  this.geometry.verticesNeedUpdate = true;
		} 
	}	
			
	return line;
}

var stationStarLine = [];
var repateAnimation = [] ;
var startsLineConnect = [];

/*  startsLineConnect.push(new THREE.Vector2(0,1)); */
startsLineConnect.push(new THREE.Vector2(5,10));
/* startsLineConnect.push(new THREE.Vector2(3,6)); 
startsLineConnect.push(new THREE.Vector2(8,20));  */

var startsLine = [];
var convertLine = false;
var CureentTime = 0.0;
//统一的数据更新
RO.UpDate = function ( context, config ) {
	
	   CureentTime ++;
	   if(CureentTime > 20.0)
	   {
		   //convertLine = !convertLine;
	   }
	   
	  //更新卫星位置
	  if( this.sputniks && this.sputniks.length > 0 ){
            for (var i = 0; i < 1; i++) {
				//存储的模型
                var sputnik = this.sputniks[0];
				var point = sputnik.position;
				var pos = RO.Math.cartesianToSpherical(point.x,point.y,point.z);
				 window.EarthGlobalConfig.EarthAngle = pos.x;
            }
        } 
	  
      if( this.sputniks ){
            for (var i = 0; i < this.sputniks.length; i++) {
				//存储的模型
                var sputnik = this.sputniks[i];
				var sputnik0 = this.sputniks2[i];
				//存储的模型运行的路径
				var linePoint = this.lineAnimation[i];
				var modelTime = this.modelTime[i];
				var modelDelta = this.timeDelta[i];
				modelTime += modelDelta;
		        this.modelTime[i] = modelTime;
				//存储的路径的大小
				var pointCount = this.pointCount[i];
				var indexTemp = parseInt(modelTime%pointCount);
				//动态改变模型的位置
				var pointLast = sputnik.position;
				var pointCurrent = linePoint[indexTemp];
		
				sputnik.position = pointCurrent;
				var point = pointCurrent.clone();
				point.normalize();
				point.multiplyScalar( 25.0 );
				point.x += pointCurrent.x;
				point.y += pointCurrent.y;
				point.z += pointCurrent.z;
				sputnik0.position = point;
            }
        } 
		
		if( this.sputniks && this.sputniks.length > 0 ){
			
			if(startsLine.length == 0)
			{
				for (var i = 0; i < startsLineConnect.length; i++) {
					var line = startsLineConnect[i];
					var indexStart = line.x;
					var indexEnd = line.y;
					var sputnik0 = this.sputniks[indexStart];
					var sputnik1 = this.sputniks[indexEnd];
					
					/*  var isIntersection =  RO.Math.LineIntersectionSphere(sputnik0.position,sputnik1.position,config.radius);
					if(!isIntersection)
					{ */
						var dynamicline = new RO.Util.CreatSimpleline(sputnik0.position,sputnik1.position);
						startsLine.push( dynamicline );
						this.starLineContainer.add(dynamicline);
					/* }
					else{ 
						
						var dynamicline = new RO.Util.CreatSimpleline(sputnik0.position,sputnik0.position);
						startsLine.push( dynamicline );
						this.starLineContainer.add(dynamicline);
					} */
				}
			}
			else{
				
				for (var i = 0; i < startsLineConnect.length; i++) {
					
					var line = startsLineConnect[i];
					var indexStart = line.x;
					var indexEnd = line.y;
					
					var sputnik0 = this.sputniks[indexStart];
					var sputnik1 = this.sputniks[indexEnd];
					
					var start = sputnik0.position;
					var end = sputnik1.position;
					 
					 var dynamicline = startsLine[i];
					 
					//var isIntersection =  RO.Math.LineIntersectionSphere(start,end,config.radius);
					/*  if(!isIntersection)
					{
						if(convertLine)
						{ */
							//dynamicline.setStart(start); 
						    //dynamicline.setEnd(end); 
						/* }
						else{
							
							dynamicline.setStart(start); 
						     dynamicline.setEnd(end); 
						}
						 */
					/* }
					else{
						
						dynamicline.setEnd(start);
					    dynamicline.setStart(start); 
					} */
					dynamicline.setEnd(end);
					dynamicline.setStart(start);
					dynamicline.update();
					
				}
			}
            
        } 
		
		
		//更新卫星上的光点
		if(this.LightParticles)
		{
			for(var i = 0;i < this.LightParticles.length;i++)
			{
			  this.LightParticles[i].update();
			}
				
		}
		
        if(this.stationLineContainer)
		{
			for(var i = 0;i < this.stationLineContainer.children.length;i++)
			{
			  this.stationLineContainer.children[i].update();
			}
				
		}
		
		if(this.mainStations && this.mainStations.length > 0)
		{
			if(stationStarLine.length == 0)
			{
				var size = this.mainStations.length;
				for(var i = 0; i<size ;i++)	
				{
					var start = this.mainStations[i];
					
					if( this.sputniks ){
					 for (var i = 0; i < this.sputniks.length; i++) {
						//存储的模型
						var sputnik = this.sputniks[i];
						var end = sputnik.position;
						
						var dynamicline = new RO.CreatDynamicRadarBeam(start,end);
						stationStarLine.push( dynamicline );
						this.starLineContainer.add(dynamicline);
					 }
					}
					
				}				
				
			} 
			else{
				
				var stationSize = this.mainStations.length;
				
				for(var i = 0; i<stationSize ;i++)	
				{
					var start = this.mainStations[i];
					var size = stationStarLine.length;
					
					for(var i = 0 ;i<size ;i++)
					{
						var sputnik = this.sputniks[i];
						var end = sputnik.position;
						var isIntersection = RO.Math.isIntersectionSphere(start,end);
						if( isIntersection )
						{
						  stationStarLine[i].setEnd(start);
						}
						else{
							stationStarLine[i].setEnd(end); 
						}
						
						stationStarLine[i].update();
					}
				}
			}
		}
		
		if(this.gifTextureAnimation){
			this.gifTextureAnimation.update(0.1);
		}
		if(repateAnimation.length > 0){
			for(var i = 0; i< repateAnimation.length; i++)
			{
				repateAnimation[i].update(0.1);
			}
		}
}

RO.CreatDynamicRadarBeam = function(start,end){
	RO.BaseObject.call( this );
	
    var cylinder = new THREE.CylinderGeometry(15,0.1,1,20,20,true);
	var mTranslate = new THREE.Matrix4();
	mTranslate.makeTranslation(0,0.5,0.0);
	
	var m = new THREE.Matrix4();
	m.makeRotationX( Math.PI/2 );
	
    //m.scale(new THREE.Vector3(1.0,100.0,1.0));
	m.multiply(mTranslate);
	
	cylinder.applyMatrix(m);
	cylinder.matrixAutoUpdate = true;
   // cylinder.applyMatrix(new THREE.Matrix4().makeTranslation(0,-0.5,0));
	var texture = THREE.ImageUtils.loadTexture("./img/light2.png");
	var  radarTextureAnimation = new RO.Util.repeatTextureAnimator( texture,1); 
	repateAnimation.push(radarTextureAnimation);
	
	var material = new THREE.MeshPhongMaterial({map:texture});   //材料
	material.transparent = true;
	material.opacity = 0.9;
	material.blending = THREE.AdditiveBlending; //NoBlending NormalBlending AdditiveBlending SubtractiveBlending MultiplyBlending
	material.depthWrite = false;
	material.depthTest = true;
	material.specularMap  = THREE.ImageUtils.loadTexture("./img/nova.png");
	material.specular = new THREE.Color(0x00ffff);
	material.side = THREE.DoubleSide;

	var RadarBeam = new THREE.Mesh(cylinder,material);
	RadarBeam.startPnt = start;
	RadarBeam.update = function(){	
		//if(line.geometry)
		{
		   //uniforms.currentTime.value += 0.5;
		}	
	}
	
	RadarBeam.setStart = function(pos){
		this.lookAt( pos );
		/* this.matrixAutoUpdate = true;
		RadarBeam.updateMatrix(); */
	}
	
	RadarBeam.setEnd = function(pos){
		var len = RO.Math.GetLength(this.startPnt,pos);
		if(len == 0)
		{
			return ;
		}
		this.scale.set(1,1,15);
		this.position = pos;
		this.setStart(this.startPnt);

	}
	
	return RadarBeam;
}

RO.CreatDynamicRadarBeam.prototype = Object.create( RO.BaseObject.prototype );

//根据卫星数据，加载卫星模型
RO.drawSputniksAndLine = function ( context, config ) {
	
	RO.BaseObject.call( this );
	
    // SPUTNIKS
    this.sputniks = [];
	this.lineAnimation = [];
	this.modelTime = [];
	this.timeDelta = [];
	this.pointCount = [];
	
	this.sputniks2 = [];
	
	 var starLineContainer = this.starLineContainer = new THREE.Object3D();
	
    var lineS = window.lineData;
	
	var loader = new THREE.STLLoader();
				loader.addEventListener( 'load', function ( event ) {

					var geometry = event.content;
					var material = new THREE.MeshPhongMaterial( { ambient: 0xff5533, color: 0xff5533, specular: 0x111111, shininess: 200 } );
					var mesh = new THREE.Mesh( geometry, material );
					mesh.scale.set( 0.02, 0.02, 0.02 );
					mesh.castShadow = false;
					mesh.receiveShadow = false;

					for(var i = 0;i<lineS.lines.length;i++)
					{
						var line = lineS.lines[i];
						var modelID = line.model_id; //模型速度
						var points = line.points;
						var lineColor = line.lineColor;
						var lineVisible = line.lineVisible;
						var lineId = line.line_id;
						var lineName = line.lineName;
						
						RO.addSputnikAndLine( context,config,container,mesh,lineId,modelID,config.radius*RO.RadiusScale, lineName,lineColor,lineVisible,points);
					}

				} );
				loader.load( './assets/earth/model.stl' );
				
	/* var loader = new THREE.JSONLoader();
		loader.load(
			URL = "./assets/earth/station_b.js",
			function ( geometry, materials ) {
				var m = new THREE.MeshBasicMaterial( { color: 0xff00ff });
				var object = new THREE.Mesh( geometry, m );
				object.position.x = 0.0;
				object.position.y = 0.0;
				object.position.z = 250.0;
				object.rotation.x = .0;
				object.scale.set( 0.3, 0.3, 0.3 );
				object.matrixAutoUpdate = true;
				object.matrixWorldNeedsUpdate = true;
				object.updateMatrix();
				
				for(var i = 0;i<lineS.lines.length;i++)
				{
					var line = lineS.lines[i];
					var modelID = line.model_id; //模型速度
					var points = line.points;
					var lineColor = line.lineColor;
					var lineVisible = line.lineVisible;
					var lineId = line.line_id;
					
					RO.addSputnikAndLine( context,config,container,object,lineId,modelID,config.radius, lineColor,lineVisible,points);
				}
				
			}
		); */
		
	return starLineContainer ;
}

RO.drawSputniksAndLine.prototype = Object.create( RO.BaseObject.prototype );

//绘制卫星模型和卫星线
RO.addSputnikAndLine = function ( context, config ,container,modelobject, lineId,modelID,radius, lineName,lineColor,lineVisible,points ) {
	
    RO.BaseObject.call( this );
   
    var scope = this;
    
	var startPoint ;
	var dataRadius = 6378.137*4;
	var pointCount = points.length/3;
	var geoRadius;
	
	if(pointCount >1)
	{	
       var x= points[0];
	   var z= points[1];
	   var y= points[2];

	   startPoint = new THREE.Vector3(x/dataRadius*radius,y/dataRadius*radius,z/dataRadius*radius);  
	   geoRadius = Math.sqrt(Math.pow(startPoint.x,2)+Math.pow(startPoint.y,2)+Math.pow(startPoint.z,2));
	   
	}
	
	var pointList = [] ;
	
	for(var i = 0;i<pointCount;i++)
	{
		var x=points[3*i]/dataRadius*radius;
		var z=points[3*i+1]/dataRadius*radius;
		var y=points[3*i+2]/dataRadius*radius;
		pointList.push(new THREE.Vector3(x,y,z));
	}
	
	//绘制人造卫星线
	if(lineVisible)
	{
		var lineGeometry = new THREE.Geometry();
		lineGeometry.vertices = pointList;
		
		if(RO.LineType == 0) //实线
		{
			var lineMaterial = new THREE.LineBasicMaterial({color: lineColor});
			var line = new THREE.Line(lineGeometry,lineMaterial);
		    scope.starLineContainer.add( line );
		}
		else if(RO.LineType == 1) //宽线
		{
			 
        var meshLine = new MeshLine();
		meshLine.setGeometry( lineGeometry );

		var resolution = new THREE.Vector2( window.innerWidth, window.innerHeight );
		var lineMaterial = new MeshLineMaterial( {
			useMap: false,
			useAlphaMap: false,
			color: new THREE.Color( lineColor ),
			opacity: 0.2,
			resolution: resolution,
			sizeAttenuation: false,
			lineWidth: 5,
			near: config.camera.near,
			far: config.camera.far,
			depthTest: true,
			depthWrite: true,
			transparent: true,
			//blending: THREE.AdditiveBlending,
			});
		
		  var line = new THREE.Mesh( meshLine.geometry, lineMaterial );
		  scope.starLineContainer.add( line ); 
		}
		else //虚线
		{
			var material = new THREE.LineDashedMaterial({
				vertexColors: false,
				color: lineColor,
				dashSize: 2,
				gapSize: 2,
				scale: 1
			});
			
			lineGeometry.computeLineDistances(); //需要调用此方法，要不然没有虚线
			var line = new THREE.Line(lineGeometry,material);
			scope.starLineContainer.add( line );

		}
	
	}
	
	
		
		function textures (lineName) {
			
			var canvas = document.createElement( 'canvas' );
			var ctx = canvas.getContext( '2d' );

			canvas.width = 64;
			canvas.height = 64;

			var colors = {
			  border: '#000000',
			  top: '#9d94a7',
			  bottom: '#796e8c'
			}
			
			ctx.fillStyle = colors.border;
			ctx.fillRect(0, 0, 64, 64);
			ctx.fillStyle = '#fff';
			ctx.strokeStyle = '#fff';
			ctx.font = "bold 3px '字体','字体','微软雅黑','宋体'";
			ctx.textBaseline = 'hanging';
			ctx.fillText(lineName ,0 ,0);
			ctx.globalAlpha = 0.0; 
			
			
			var canvasTexture = new THREE.Texture(canvas);
			canvasTexture.wrapS = THREE.RepeatWrapping;
			canvasTexture.wrapT = THREE.RepeatWrapping;
			canvasTexture.needsUpdate = true;
			
			return canvasTexture;
	  }
	  
	  function CreatePoint(texture,size,color)
	  {
		   var particlesGeo =  new THREE.Geometry();
			particlesGeo.dynamic = true;
			
			var uniforms =  {
				size: { type: "f", value: size },
				color:     { type: "c", value: new THREE.Color(color) },
				texture:   { type: "t", value: texture },
			};
			
			var shaderMaterial = new THREE.ShaderMaterial( {
				uniforms: 		uniforms,
				vertexShader:   RO.ShaderChunk.pointLightShader.vertexShader,
				fragmentShader: RO.ShaderChunk.pointLightShader.fragmentShader,
				blending: 		THREE.AdditiveBlending,
				depthTest: 		true,
				depthWrite: 	false,
				transparent:	true,
			    sizeAttenuation: false,
			});
	
			particlesGeo.vertices.push( new THREE.Vector3(0,0,0.0) );
			
			var pSystem = new THREE.ParticleSystem( particlesGeo, shaderMaterial );
			pSystem.dynamic = true;
			pSystem.position = startPoint;
			pSystem.rotation.x += Math.PI;
			
			return pSystem;
	  }
		    
			
	  var starName = CreatePoint(textures(lineName),60.0,0x00ff00);
	  
			
	 scope.sputniks2.push( starName );
	 scope.starLineContainer.add( starName ); 
	
	
	
	//三维文字
	 /* var text3d = new THREE.TextGeometry( "GEO", {
			size: 8,
			height: 2,
			curveSegments: 2,
			font: "helvetiker"

		});

	//text3d.computeBoundingBox();
	var textMaterial = new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: false } );
	var text = new THREE.Mesh( text3d.clone(), textMaterial );
	
	var lon = 110.0;
	var lat = 0.0;
		
	text.position = KMG.Math.getPoint3D(lon,lat,geoRadius);
	text.rotation.y = -Math.PI;
	text.lookAt(new THREE.Vector3(0.0,0.0,0.0)); */
	
	//scope.sputniks2.push( text );
	//scope.sputniks2.push( text );
	//scope.starLineContainer.add( text ); 
	
	var modelobjectClone ;
	
	if(false)
	{
		modelobjectClone = modelobject.clone();
	}
	else{
		
		var texture = THREE.ImageUtils.loadTexture( "./img/timg.png" );
		modelobjectClone = CreatePoint(texture,50.0,lineColor);
	}
	 
    modelobjectClone.position = startPoint;
	scope.sputniks.push( modelobjectClone );
	scope.starLineContainer.add( modelobjectClone );
	scope.timeDelta.push(modelID);
	scope.modelTime.push(0); 

	//三个 GEO卫星，路径固定不变
	/* if(lineId == 1)
	{
		var spointList = [] ;
		
		var lon = 110.0;
		var lat = 0.0;
		
		spointList.push(KMG.Math.getPoint3D(lon,lat,geoRadius));
		 
	    scope.lineAnimation.push(spointList);
	    scope.pointCount.push(1);
	}
	else if(lineId == 2)
	{
		var spointList = [] ;
		
		var lon = 110.0 + 12;
		var lat = 0.0;
		
		spointList.push(KMG.Math.getPoint3D(lon,lat,geoRadius));
		
		spointList.push(new THREE.Vector3(x,y,z));
		
		scope.lineAnimation.push(spointList);
	   scope.pointCount.push(1);
	}
	else if(lineId == 3)
	{
		var spointList = [] ;
		
		var lon = 140.0 -5;
		var lat = 0.0;
		
		spointList.push(KMG.Math.getPoint3D(lon,lat,geoRadius));
		
		spointList.push(new THREE.Vector3(x,y,z));
		
		scope.lineAnimation.push(spointList);
		scope.pointCount.push(1);
	}
	else{ */
		scope.lineAnimation.push(pointList);
		scope.pointCount.push(pointCount);
	//}
		
    return line;
}

RO.drawSputniksAndLine.prototype = Object.create( RO.BaseObject.prototype );


RO.drawSputniksLineLight  = function( context, config) {
	
	RO.BaseObject.call( this );
	
	var lightParticleContainer = this.lightParticleContainer = new THREE.Object3D();

	
    var lineS = window.lineData;
    this.LightParticles = [];
	var particleCount = 1.0;
	var particleSize = 100.0;	
    var dataRadius = 6378.137*4;
	var radius = config.radius*RO.RadiusScale;
		
	for(var i = 0;i<lineS.lines.length;i++)
	{
		var line = lineS.lines[i];
		var points = line.points;
		var pointCount = points.length/3.0;
		var lineColor = line.lineColor;
		var lineVisible = line.lineVisible;
		var lineId = line.line_id;
		//if( lineVisible == true)
		if( true)
		{
		    var pointList = [] ;
			for(var j = 0;j<pointCount;j++)
			{
				var x=points[3*j]/dataRadius*radius;
				var z=points[3*j+1]/dataRadius*radius;
				var y=points[3*j+2]/dataRadius*radius;
				pointList.push(new THREE.Vector3(x,y,z));
			}
			
			var geoRadius;
	
			if(pointCount >1)
			{	
			   var x= points[0];
			   var z= points[1];
			   var y= points[2];

			   startPoint = new THREE.Vector3(x/dataRadius*radius,y/dataRadius*radius,z/dataRadius*radius);  
			   geoRadius = Math.sqrt(Math.pow(startPoint.x,2)+Math.pow(startPoint.y,2)+Math.pow(startPoint.z,2));
			}
	
			var particlesGeo =  new THREE.Geometry();
			    particlesGeo.dynamic = true;
			
			if(lineId == 1)
			{
				var spointList = [] ;
				
				var lon = 110.0;
				var lat = 0.0;
				
				var point = KMG.Math.getPoint3D(lon,lat,geoRadius);
				
				var pointAttibute = point.clone();
				pointAttibute.moveIndex = 0;
			    pointAttibute.nextIndex = 0;
				pointAttibute.lerpN = 0;
				pointAttibute.path = [];
				pointAttibute.path.push(point);
				pointAttibute.size = 0;	
				particlesGeo.vertices.push( pointAttibute );	
			}
			else if(lineId == 2)
			{
				var spointList = [] ;
				
				var lon = 110.0 + 12;
				var lat = 0.0;
				
				var point = KMG.Math.getPoint3D(lon,lat,geoRadius);
				
				var pointAttibute = point.clone();
				pointAttibute.moveIndex = 0;
			    pointAttibute.nextIndex = 0;
				pointAttibute.lerpN = 0;
				pointAttibute.path = [];
				pointAttibute.path.push(point);
				pointAttibute.size = 0;	
				particlesGeo.vertices.push( pointAttibute );	
			}
			else if(lineId == 3)
			{
				var spointList = [] ;
				
				var lon = 140.0 -5;
				var lat = 0.0;
				
			    var point = KMG.Math.getPoint3D(lon,lat,geoRadius);
				
				var pointAttibute = point.clone();
				pointAttibute.moveIndex = 0;
			    pointAttibute.nextIndex = 0;
				pointAttibute.lerpN = 0;
				pointAttibute.path = [];
				pointAttibute.path.push(point);
				pointAttibute.size = 0;	
				particlesGeo.vertices.push( pointAttibute );	
				
			}
			else
			{
				for( var s=0; s< particleCount; s++ ){
	
					var desiredIndex = s / particleCount * pointList.length;
					var rIndex = RO.Math.constrain(Math.floor(desiredIndex),0,pointList.length-1);

					var point = pointList[rIndex];	
					var pointAttibute = point.clone();
		
					pointAttibute.moveIndex = rIndex;
					var nextIndex  = rIndex+1;
					if(nextIndex >= points.length )
						nextIndex = 0;
					pointAttibute.nextIndex = nextIndex;
					pointAttibute.lerpN = 0;
					pointAttibute.path = pointList;
					pointAttibute.size = particleSize;	
					particlesGeo.vertices.push( pointAttibute );					
				} 
			}
			
			var uniforms =  {
				size: { type: "f", value: 50.0 },
				color:     { type: "c", value: new THREE.Color(0xffffff) },
				texture:   { type: "t", value: THREE.ImageUtils.loadTexture( "./img/particleA.png" ) },
			};
			
			var shaderMaterial = new THREE.ShaderMaterial( {
				uniforms: 		uniforms,
				vertexShader:   RO.ShaderChunk.pointLightShader.vertexShader,
				fragmentShader: RO.ShaderChunk.pointLightShader.fragmentShader,
				blending: 		THREE.AdditiveBlending,
				depthTest: 		true,
				depthWrite: 	false,
				transparent:	true,
				// sizeAttenuation: true,
			});
		
		    uniforms.color.value = new THREE.Color(lineColor);
		   
			var pSystem = new THREE.ParticleSystem( particlesGeo, shaderMaterial );
			pSystem.dynamic = true;
			this.lightParticleContainer.add( pSystem ); 
			this.LightParticles.push(pSystem);
			
			pSystem.update = function(){
				
				for( var i in this.geometry.vertices ){						
					var particle = this.geometry.vertices[i];
					var path = particle.path;
					var moveLength = path.length;
					
					particle.lerpN += 1.0;
					if(particle.lerpN > 1){
						particle.lerpN = 0;
						particle.moveIndex = particle.nextIndex;
						particle.nextIndex++;
						if( particle.nextIndex >= path.length ){
							particle.moveIndex = 0;
							particle.nextIndex = 1;
						}
					}

					var currentPoint = path[particle.moveIndex];
					var nextPoint = path[particle.nextIndex];
					particle.copy( currentPoint );	
				}
				this.geometry.verticesNeedUpdate = true;
			}	
		}
	}

    return lightParticleContainer ;	
}

RO.drawSputniksLineLight.prototype = Object.create( RO.BaseObject.prototype );	

RO.drawStationLine =  function( context, config)
{
	RO.BaseObject.call( this );
	
	var stationRadius = config.radius;
	
	var stationLineContainer = this.stationLineContainer = new THREE.Object3D();
	var stationData = window.data;
	var normalStations = this.normalStations = [];
	var mainStations = this.mainStations = [];
	
	for(var i = 0;i<stationData.locations.length;i++)
	{
		var location = stationData.locations[i];
		var name = location.name;
		
		if(name == "北京")
		{
			mainStations.push(KMG.Math.getPoint3D(location.planet_v,location.planet_u,stationRadius));
		}
		else{
			normalStations.push(KMG.Math.getPoint3D(location.planet_v,location.planet_u,stationRadius));
		}
	}
	for(var i = 0;i< normalStations.length;i++)
	{   
		stationLineContainer.add(RO.Util.CreatFlyline(stationRadius*1.05,mainStations[0],normalStations[i]));
	}	
	
    return 	stationLineContainer;
	    
}

RO.drawStationLine.prototype = Object.create( RO.BaseObject.prototype );
		
RO.drawStationPoint =  function( context, config)
{
	RO.BaseObject.call( this );
	
	var stationRadius = config.radius;
	
	var stationPointContainer = this.stationPointContainer = new THREE.Object3D();
	var stationData = window.data;
	var normalStations = [];
	var mainStations = [];
	
	for(var i = 0;i<stationData.locations.length;i++)
	{
		var location = stationData.locations[i];
		var name = location.name;
		
		if(name == "北京")
		{
			mainStations.push(KMG.Math.getPoint3D(location.planet_v,location.planet_u,stationRadius));
		}
		else{
			normalStations.push(KMG.Math.getPoint3D(location.planet_v,location.planet_u,stationRadius));
		}
	}
		
	//timg.gif star_particle.png
	var runnerTexture = new THREE.ImageUtils.loadTexture( './img/particleA.png' );
	runnerTexture.needsUpdate = true;
	
	this.gifTextureAnimation = new RO.Util.gifTextureAnimator( runnerTexture, 1, 1, 1, 2 ); // texture, #horiz, #vert, #total, duration.
	
	var runnerMaterial = new THREE.MeshBasicMaterial( { map: runnerTexture, side:THREE.DoubleSide } );
	runnerMaterial.transparent = true;
	runnerMaterial.opacity = .9;
	runnerMaterial.blending = THREE.AdditiveBlending;
    runnerMaterial.depthWrite = false;
	runnerMaterial.color.value = RO.Util.getRandomColor();
	
	
	function createFaceMesh(rotate) {
		var h = Math.random()*0.5+ 5;
		var geometry = new THREE.PlaneGeometry(5.3, h,1);
		var mesh = new THREE.Mesh(geometry, runnerMaterial); 
		
		mesh.rotation.set(rotate, 0.0, 0, 'YXZ');

		return mesh;
	}
		
	for(var i = 0;i< normalStations.length;i++)
	{   
			var plane = createFaceMesh(0.0);

			var meshObject = new THREE.Object3D();
			meshObject.position.copy( normalStations[i] );
			meshObject.lookAt( new THREE.Vector3(0, 0, 0.0) );
			meshObject.matrixAutoUpdate = false;
			meshObject.updateMatrix();
			meshObject.add(plane);
			
			stationPointContainer.add(meshObject);
			
			RO.pointLocations(normalStations[i]);
	}
	{
		var plane = createFaceMesh(0.0);

			var meshObject = new THREE.Object3D();
			meshObject.position.copy( mainStations[0] );
			meshObject.lookAt( new THREE.Vector3(0, 0, 0.0) );
			meshObject.matrixAutoUpdate = false;
			meshObject.updateMatrix();
			meshObject.add(plane);
			
			stationPointContainer.add(meshObject);
			
			RO.pointLocations(mainStations[0]);
	}
	
    return 	stationPointContainer;
	    
}

RO.drawStationPoint.prototype = Object.create( RO.BaseObject.prototype );

 RO.addLightRay = function ( _pos, light_material ) {

 RO.BaseObject.call( this );
 
       var cometTexture = KMG.TextureMap.loadTexture("./img/lightray_blue.jpg");
		cometTexture.wrapS = cometTexture.wrapT = THREE.ClampToEdgeWrapping;
		cometTexture.format = THREE.RGBAFormat;
		cometTexture.needsUpdate = true;
	    light_material.map = cometTexture;
		var mt = light_material.clone();
		function createFaceMesh(rotate) {
			var h = Math.random()*0.5+ 205;
			var geometry = new THREE.PlaneGeometry(305.3, h,1);
			var mesh = new THREE.Mesh(geometry, mt); 
			
			mesh.rotation.set(rotate, 0.0, 0, 'YXZ');
			mesh.position.z -= 160;

			return mesh;
		}
		
	var plane = createFaceMesh(0.0);
	var m = new THREE.Matrix4();
	m.makeRotationX( Math.PI/2 );
	plane.applyMatrix(m);
	plane.matrixAutoUpdate = false;
	
	// cross plane of ray
	var plane2 = plane.clone();
	plane2.rotation.y = Math.PI/2 ;
	plane2.rotation.x = 0.0;
	plane2.matrixAutoUpdate = true;
	plane2.updateMatrix();
	plane.add( plane2 );
	
	var meshObject = new THREE.Object3D();
	meshObject.position.copy( _pos );
	meshObject.lookAt( new THREE.Vector3(0, 0, 0.0) );
	meshObject.matrixAutoUpdate = false;
	meshObject.updateMatrix();
	meshObject.add(plane);
	
	return meshObject;
}

RO.addLightRay.prototype = Object.create( RO.BaseObject.prototype );

RO.pointLocations = function (position)
{
	RO.BaseObject.call( this );
	
	var max_opacity = .8;
    var material_yellow = new THREE.MeshBasicMaterial({
    	transparent : true,
    	// alphaTest: .5,
	    opacity : 0.5,
	    color : new THREE.Color( 0xffde00 ),
	    // color : new THREE.Color( 0xff0000 ),
	    blending : THREE.AdditiveBlending,
	    side : THREE.DoubleSide,
	    depthWrite : false	,
		fog: false
    });
	
	var material_blue = new THREE.MeshBasicMaterial({
    	transparent : true,
    	// alphaTest: .5,
	    opacity : 1.0,
	    color : new THREE.Color( 0x0000ff ),
	    // color : new THREE.Color( 0xff0000 ),
	    blending : THREE.AdditiveBlending,
	    side : THREE.DoubleSide,
	    depthWrite : false,
		fog: false
    });

    var material_white = new THREE.MeshBasicMaterial({
    	transparent : true,
    	// alphaTest: .5,
	    opacity : 0.7,
	    blending : THREE.AdditiveBlending,
	    side : THREE.DoubleSide,
	    depthWrite : false,
		fog: false
	    // wireframe: true
    });

    // make base location shape
    var hex = Utils.createHexagon( 0.15*0.5, false, undefined );
	hex.position = position;
	
    // additional shape - the ring
    var hex_ring = Utils.createHexagon( 0.2*0.5, false, undefined, .02 );
    hex.add( hex_ring );
	
    //var r = planet.radius*1.005;
    var zero = new THREE.Vector3();

	var geo_yellow = new THREE.Geometry();//hex.geometry.clone();
	var geo_white = new THREE.Geometry();//hex.geometry.clone();
	var geo_blue = new THREE.Geometry();
	
	//var geo  = geo_blue; 
   // geo.merge( hex.geometry, hex.matrixWorld );
	//geo.merge( hex_ring.geometry, hex_ring.matrixWorld );	
    
	
	var light  = addLightRay( hex.position, material_blue );
	this.starLineContainer.add( light );
	
    // METHODS
} 

RO.pointLocations.prototype = Object.create( RO.BaseObject.prototype );







	